package com.xishu.controller;

import com.xishu.bo.pay.PayRequest;
import com.xishu.cash.QfPayClient;
import com.xishu.config.Constant;
import com.xishu.entity.order.Order;
import com.xishu.service.order.callback.OrderCallBackService;
import com.xishu.entity.shop.Shop;
import com.xishu.response.ResponseData;
import com.xishu.response.ResponseStatus;
import com.xishu.response.VerifyUtil;
import com.xishu.service.LockService;
import com.xishu.service.order.base.OrderService;
import com.xishu.service.ShopService;
import com.xishu.util.AES;
import com.xishu.util.Tools;
import io.swagger.annotations.ApiOperation;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;

import static com.xishu.config.Constant.ORDER_PAY_TYPE_ALIPAY;
import static com.xishu.config.Constant.ORDER_PAY_TYPE_WEIXIN;
import static com.xishu.response.ResponseStatus.SYSTEM_BUSY;

@RestController
public class PaymentController implements Tools {
    private LockService localLockService = LockService.getInstance();
    private static Logger logger = LoggerFactory.getLogger(PaymentController.class);

    /**
     * 付款码付款
     *
     * @param payRequest
     * @return
     */
    @ApiOperation(value = "付款码付款")
    @PutMapping(value = ("/pay/code"), produces = ("application/json;charset=UTF-8"))
    public ResponseData payWithPayCode(@RequestBody PayRequest payRequest) throws Exception {
        Long orderId = payRequest.getOrderId();
        Long shopId = payRequest.getShopId();
        Integer payType = payRequest.getPayType();
        String payCode = payRequest.getPayCode();
        VerifyUtil.verify(() -> orderId != null);
        VerifyUtil.verify(() -> shopId != null);
        VerifyUtil.verify(() -> payType != null);
        VerifyUtil.verify(() -> isNotEmpty(payCode));

        OrderService orderService = OrderService.getInstance();
        String lockKey = orderService.getLockKey(shopId, orderId);

        Object lock = localLockService.getLock(lockKey);

        synchronized (lock) {
            Order order = OrderService.getInstance().findOrder(shopId, orderId);

            if (!getBoolean(order.getVipOrder()) && order.getPayType() != null) {
                VerifyUtil.throwError(SYSTEM_BUSY);
            }

            //添加打印机
            if (payRequest.getPrinterId() != null) {
                order.setPrinterId(payRequest.getPrinterId());
            }

            Shop shop = ShopService.getInstance().findShopById(shopId);
            QfPayClient qfPayClient = new QfPayClient(AES.decrypt(shop.getQfCode()), AES.decrypt(shop.getQfKey()), shop.getQfSid());

            String result = null;

            if (getInt(payType) == Constant.PAY_TYPE_WEIXIN) {
                result = qfPayClient.paymentCodePay(payCode, order, "800208");
                order.setPayType(ORDER_PAY_TYPE_WEIXIN);
            } else if (getInt(payType) == Constant.PAY_TYPE_ALI_PAY) {
                result = qfPayClient.paymentCodePay(payCode, order, "800108");
                order.setPayType(ORDER_PAY_TYPE_ALIPAY);
            }

            JSONObject jsonObject = JSONObject.fromObject(result);
            String statusResult = jsonObject.getString("respcd");
            boolean payResult = equals(statusResult, "0000");

            String syssn = jsonObject.getString("syssn");
            order.setSyssn(syssn);

            //支付成功了，开始回调
            if (payResult) {
                logger.info("shopId {} order {} pay success", shopId, orderId);
                payCallback(order);
            } else if (Arrays.asList("1143", "1145").contains(statusResult)) {
                boolean payOk = false;
                //2秒1次，重试30次
                //等待状态码，需要定时查询
                String respcd = null;
                for (int i = 0; i < 30; i++) {
                    try {
                        String queryResult = qfPayClient.query(order);
                        JSONObject queryJsonResult = JSONObject.fromObject(queryResult);
                        JSONArray jsonArray = queryJsonResult.getJSONArray("data");
                        if (jsonArray.isEmpty()) {
                            break;
                        }

                        JSONObject jsonData = jsonArray.getJSONObject(0);
                        respcd = jsonData.getString("respcd");
                    } catch (Exception e) {
                        //有异常就退出
                        logger.error("e", e);
                        break;
                    }

                    if (equals(respcd, "0000")) {
                        payOk = true;
                        break;
                    } else if (Arrays.asList("1143", "1145").contains(respcd)) {
                        Thread.sleep(2000);
                        continue;
                    } else {
                        //其它就是支付失败了
                        VerifyUtil.throwError(ResponseStatus.PAY_SYSTEM_ERROR);
                    }

                }

                if (payOk) {
                    payCallback(order);
                }
            } else {
                VerifyUtil.throwError(ResponseStatus.PAY_SYSTEM_ERROR);
            }

            return ResponseData.emptyResponse();
        }
    }

    private void payCallback(Order order) throws Exception {
        order.setVerified(true);
        order.setPay3rd(Constant.PAY_3RD_QF);
        order.setPayedWith3rd(true);
        if (getBoolean(order.getVipOrder())) {
            OrderCallBackService.getInstance().dealVipOrder(order);
        } else {
            OrderCallBackService.getInstance().orderCallback(order);
        }
    }

}
